#include <xen/xen.h>
+#define ASCII32(a,b,c,d) \
+ (((a) << 0) | ((b) << 8) | ((c) << 16) | ((d) << 24))
+#define ASCII64(a,b,c,d,e,f,g,h) \
+ (((uint64_t)ASCII32(a,b,c,d)) | (((uint64_t)ASCII32(e,f,g,h)) << 32))
+
#pragma pack (1)
/*
};
#define ACPI_OEM_ID {'I','N','T','E','L',' '}
-#define ACPI_OEM_TABLE_ID 0x544244 /* "TBD" */
+#define ACPI_OEM_TABLE_ID ASCII32(' ','T','B','D')
#define ACPI_OEM_REVISION 0x00000002
#define ACPI_CREATOR_ID 0x00 /* TBD */
#define ACPI_CREATOR_REVISION 0x00000002
};
#define ACPI_2_0_XSDT_REVISION 0x01
+/*
+ * TCG Hardware Interface Table (TCPA)
+ */
+
+typedef struct _ACPI_2_0_TCPA_CLIENT {
+ struct acpi_header header;
+ uint16_t PlatformClass;
+ uint32_t LAML;
+ uint64_t LASA;
+} ACPI_2_0_TCPA_CLIENT;
+
+#define ACPI_2_0_TCPA_REVISION 0x02
+#define ACPI_2_0_TCPA_LAML_SIZE (64*1024)
+
/*
* Fixed ACPI Description Table Structure (FADT).
*/
/*
* Table Signatures.
*/
-#define ACPI_2_0_RSDP_SIGNATURE 0x2052545020445352LL /* "RSD PTR " */
-#define ACPI_2_0_FACS_SIGNATURE 0x53434146 /* "FACS" */
-#define ACPI_2_0_FADT_SIGNATURE 0x50434146 /* "FADT" */
-#define ACPI_2_0_MADT_SIGNATURE 0x43495041 /* "APIC" */
-#define ACPI_2_0_RSDT_SIGNATURE 0x54445352 /* "RSDT" */
-#define ACPI_2_0_XSDT_SIGNATURE 0x54445358 /* "XSDT" */
+#define ACPI_2_0_RSDP_SIGNATURE ASCII64('R','S','D',' ','P','T','R',' ')
+#define ACPI_2_0_FACS_SIGNATURE ASCII32('F','A','C','S')
+#define ACPI_2_0_FADT_SIGNATURE ASCII32('F','A','C','P')
+#define ACPI_2_0_MADT_SIGNATURE ASCII32('A','P','I','C')
+#define ACPI_2_0_RSDT_SIGNATURE ASCII32('R','S','D','T')
+#define ACPI_2_0_XSDT_SIGNATURE ASCII32('X','S','D','T')
+#define ACPI_2_0_TCPA_SIGNATURE ASCII32('T','C','P','A')
#pragma pack ()
#include "acpi/acpi2_0.h"
#include "acpi_utils.h"
#include "util.h"
+#include <xen/hvm/e820.h>
static int acpi_rsdt_add_entry_pointer(unsigned char *acpi_start,
unsigned char *entry);
+static int acpi_xsdt_add_entry_pointer(unsigned char *acpi_start,
+ unsigned char *entry);
static unsigned char *acpi_xsdt_add_entry(unsigned char *acpi_start,
unsigned char **freemem,
unsigned char *limit,
void set_checksum(void *start, int checksum_offset, int len)
{
- unsigned char sum = 0;
- unsigned char *ptr;
+ unsigned char sum = 0;
+ unsigned char *ptr;
- ptr = start;
- ptr[checksum_offset] = 0;
- while (len--)
- sum += *ptr++;
+ ptr = start;
+ ptr[checksum_offset] = 0;
+ while ( len-- )
+ sum += *ptr++;
- ptr = start;
- ptr[checksum_offset] = -sum;
+ ptr = start;
+ ptr[checksum_offset] = -sum;
}
#include "acpi_ssdt_tpm.h"
-static int acpi_tpm_tis_probe(unsigned char *acpi_start,
- unsigned char **freemem,
- unsigned char *limit)
+static void acpi_tpm_tis_probe(unsigned char *acpi_start,
+ unsigned char **freemem,
+ unsigned char *limit)
{
- int success = 1; /* not successful means 'out of memory' */
- unsigned char *addr;
- /* check TPM_DID, TPM_VID, TPM_RID in ioemu/hw/tpm_tis.c */
- uint16_t tis_did_vid_rid[] = {0x0001, 0x0001, 0x0001};
-
- /* probe for TIS interface ... */
- if (memcmp((char *)(0xFED40000 + 0xF00),
- tis_did_vid_rid,
- sizeof(tis_did_vid_rid)) == 0) {
- puts("TIS is available\n");
- addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
- AmlCode_TPM, sizeof(AmlCode_TPM));
- if (addr == NULL)
- success = 0;
- else {
- /* legacy systems need an RSDT entry */
- acpi_rsdt_add_entry_pointer(acpi_start,
- addr);
- }
- }
- return success;
+ unsigned char *addr;
+ ACPI_2_0_TCPA_CLIENT *tcpa;
+ /* check TPM_DID, TPM_VID, TPM_RID in ioemu/hw/tpm_tis.c */
+ uint16_t tis_did_vid_rid[] = {0x0001, 0x0001, 0x0001};
+ static const ACPI_2_0_TCPA_CLIENT Tcpa = {
+ .header = {
+ .signature = ACPI_2_0_TCPA_SIGNATURE,
+ .length = sizeof(ACPI_2_0_TCPA_CLIENT),
+ .revision = ACPI_2_0_TCPA_REVISION,
+ .oem_id = {'I', 'B', 'M', ' ', ' ', ' '},
+ .oem_table_id = ASCII64(' ', ' ', ' ', ' ', ' ', 'x', 'e', 'n'),
+ .oem_revision = 1,
+ .creator_id = ASCII32('I', 'B', 'M', ' '),
+ .creator_revision = 1,
+ }
+ };
+
+ /* probe for TIS interface ... */
+ if ( memcmp((char *)(0xFED40000 + 0xF00),
+ tis_did_vid_rid,
+ sizeof(tis_did_vid_rid)) != 0 )
+ return;
+
+ puts("TIS is available\n");
+ addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
+ AmlCode_TPM, sizeof(AmlCode_TPM));
+ if ( addr == NULL )
+ return;
+
+ /* legacy systems need an RSDT entry */
+ acpi_rsdt_add_entry_pointer(acpi_start, addr);
+
+ /* add ACPI TCPA table */
+ addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
+ (unsigned char *)&Tcpa,
+ sizeof(Tcpa));
+ if ( addr == NULL )
+ return;
+
+ tcpa = (ACPI_2_0_TCPA_CLIENT *)addr;
+ tcpa->LASA = e820_malloc(
+ ACPI_2_0_TCPA_LAML_SIZE, E820_RESERVED, (uint32_t)~0);
+ if ( tcpa->LASA )
+ {
+ tcpa->LAML = ACPI_2_0_TCPA_LAML_SIZE;
+ memset((char *)(unsigned long)tcpa->LASA,
+ 0x0,
+ tcpa->LAML);
+ set_checksum(tcpa,
+ FIELD_OFFSET(struct acpi_header, checksum),
+ tcpa->header.length);
+ }
+
+ acpi_rsdt_add_entry_pointer(acpi_start, addr);
}
struct acpi_20_rsdt *rsdt;
rsdp = (struct acpi_20_rsdp *)(acpi_start + sizeof(struct acpi_20_facs));
- if (rsdp->signature != ACPI_2_0_RSDP_SIGNATURE) {
+ if ( rsdp->signature != ACPI_2_0_RSDP_SIGNATURE )
+ {
puts("Bad RSDP signature\n");
return NULL;
}
rsdt = (struct acpi_20_rsdt *)
(acpi_start + rsdp->rsdt_address - ACPI_PHYSICAL_ADDRESS);
- if (rsdt->header.signature != ACPI_2_0_RSDT_SIGNATURE) {
+ if ( rsdt->header.signature != ACPI_2_0_RSDT_SIGNATURE )
+ {
puts("Bad RSDT signature\n");
return NULL;
}
+
return rsdt;
}
int found = 0;
int i = 0;
- /* get empty slot in the RSDT table */
- while (i < ACPI_MAX_NUM_TABLES) {
- if (rsdt->entry[i] == 0) {
+ /* Find an empty slot in the RSDT table. */
+ while ( i < ACPI_MAX_NUM_TABLES )
+ {
+ if ( rsdt->entry[i] == 0 )
+ {
found = 1;
break;
}
i++;
}
- if (found) {
- rsdt->entry[i] = (uint64_t)(long)entry;
+ if ( found )
+ {
+ rsdt->entry[i] = (uint64_t)(unsigned long)entry;
rsdt->header.length =
sizeof(struct acpi_header) +
(i + 1) * sizeof(uint64_t);
return found;
}
-/* Get the XSDT table */
+/* Get the XSDT table. */
struct acpi_20_xsdt *acpi_xsdt_get(unsigned char *acpi_start)
{
struct acpi_20_rsdp *rsdp;
struct acpi_20_xsdt *xsdt;
rsdp = (struct acpi_20_rsdp *)(acpi_start + sizeof(struct acpi_20_facs));
- if (rsdp->signature != ACPI_2_0_RSDP_SIGNATURE) {
+ if ( rsdp->signature != ACPI_2_0_RSDP_SIGNATURE )
+ {
puts("Bad RSDP signature\n");
return NULL;
}
xsdt = (struct acpi_20_xsdt *)
(acpi_start + rsdp->xsdt_address - ACPI_PHYSICAL_ADDRESS);
- if (xsdt->header.signature != ACPI_2_0_XSDT_SIGNATURE) {
+ if ( xsdt->header.signature != ACPI_2_0_XSDT_SIGNATURE )
+ {
puts("Bad XSDT signature\n");
return NULL;
}
return xsdt;
}
+/*
+ * Add an entry to the XSDT table given the pointer to the entry.
+ */
+static int acpi_xsdt_add_entry_pointer(unsigned char *acpi_start,
+ unsigned char *entry)
+{
+ struct acpi_20_xsdt *xsdt = acpi_xsdt_get(acpi_start);
+ int found = 0;
+ int i = 0;
+
+ /* Find an empty slot in the XSDT table. */
+ while ( i < ACPI_MAX_NUM_TABLES )
+ {
+ if ( xsdt->entry[i] == 0 )
+ {
+ found = 1;
+ break;
+ }
+ i++;
+ }
+
+ if ( found )
+ {
+ xsdt->entry[i] = (uint64_t)(unsigned long)entry;
+ xsdt->header.length =
+ sizeof(struct acpi_header) +
+ (i + 1) * sizeof(uint64_t);
+ set_checksum(xsdt,
+ FIELD_OFFSET(struct acpi_header, checksum),
+ xsdt->header.length);
+ }
+
+ return found;
+}
+
/*
add an entry to the xdst table entry pointers
copy the given ssdt data to the current available memory at
int found = 0, i = 0;
unsigned char *addr = NULL;
- /* get empty slot in the Xsdt table */
- while (i < ACPI_MAX_NUM_TABLES) {
- if (xsdt->entry[i] == 0) {
+ /* Check for an empty slot in the Xsdt table. */
+ while ( i < ACPI_MAX_NUM_TABLES )
+ {
+ if ( xsdt->entry[i] == 0 )
+ {
found = 1;
break;
}
i++;
}
- if (found) {
+ if ( found )
+ {
/* memory below hard limit ? */
if (*freemem + table_size <= limit) {
puts("Copying SSDT entry!\n");
addr = *freemem;
memcpy(addr, table, table_size);
- xsdt->entry[i] = (uint64_t)(long)addr;
*freemem += table_size;
- /* update the XSDT table */
- xsdt->header.length =
- sizeof(struct acpi_header) +
- (i + 1) * sizeof(uint64_t);
- set_checksum(xsdt,
- FIELD_OFFSET(struct acpi_header, checksum),
- xsdt->header.length);
+
+ acpi_xsdt_add_entry_pointer(acpi_start, addr);
}
}
+
return addr;
}